<?php

namespace App\Common;

use App\Exceptions\BusinessException;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;

/**
 * 工具类
 *
 * @author WangBin
 * @date 2021-08-12
 * @package App\Http\Common
 */
class Tools
{
    /**
     * 获取uniqueId
     *
     * @param string $prefix
     * @return string
     */
    public static function getUniqid($prefix = '')
    {
        return uniqid($prefix,true);
    }

    /**
     * 获取当前的毫秒数
     *
     * @return float
     */
    public static function getMSec()
    {
        list($msec, $sec) = explode(' ', microtime());
        return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
    }

    /**
     * 获取当前的秒数
     *
     * @return float
     */
    public static function getSec()
    {
        return time();
    }

    /**
     * 生成编号
     *
     * @param string $bnKey
     * @return string
     * @throws BusinessException
     */
    public static function buildBn(string $bnKey)
    {
//        if(!key_exists($bnKey, BnFormatConfig::BN_FORMAT_MAP)) {
//            throw new BusinessException(ResponseCode::BN_KEY_NOT_FOUND);
//        }
        // 获取缓存自增值
        $count = 1;
        if(Cache::has($bnKey)) {
            $count = Cache::get($bnKey);
        } else {
            // 有效期为当日
            Cache::put($bnKey, 1, Carbon::now()->diffInSeconds(Carbon::tomorrow()));
        }
        $prefix = BnFormatConfig::BN_FORMAT_MAP[$bnKey]['prefix'];
        $pad = BnFormatConfig::BN_FORMAT_MAP[$bnKey]['pad'];
        $bn = $prefix . date('Ymd') . str_pad($count,$pad,'0',STR_PAD_LEFT);
        Cache::increment($bnKey);
        return $bn;
    }

    /**
     *  随机串
     */
    public static function buildRandomBn($prefix = ""): string
    {
        return $prefix . date('YmdHis') . str_pad(rand(0,9999999),7,'0',STR_PAD_LEFT);
    }

    /**
     * 生成手机号掩码
     * 示例：18809091010 => 188****1010
     *
     * @param string $mobile
     * @return string
     */
    public static function makeMobileMask(string $mobile)
    {
        //截取手机号号前3位
        $prefix = substr($mobile,0,3);
        //截取手机号后4位
        $suffix = substr($mobile,-4,4);
        return sprintf("%s****%s", $prefix, $suffix);
    }

    /**
     * 生成卡号掩码
     * 示例：6685000300000084 => **** 0084
     *
     * @param string $cardNo
     * @return string
     */
    public static function makeCardNoMask(string $cardNo)
    {
        //截取卡号号后4位
        $suffix = substr($cardNo,-4,4);
        return sprintf("**** %s", $suffix);
    }

    /**
     *
     */
    public static function arrval($arr,$key,$default="")
    {
        if(!is_array($arr) || is_null($key))
            return $default;

        return (empty($arr[$key]) ? $default : $arr[$key]);
    }

    /**
     * 获取截断的地址信息
     *
     * @param string $addressArea
     * @param int $index
     * @param string $separator
     * @return mixed|string
     */
    public static function getOrderArea(string $addressArea, int $index = 0, string $separator = ':')
    {
        $area = explode($separator, $addressArea);
        return $area[$index] ?? '';
    }

     /* 解密 AES加密串
     *
     * @param string $encryptString
     * @param string $key
     * @param string $iv
     * @param string $algo
     * @return false|string
     */
    public static function decryptAesString(string $encryptString , string $key = '', string $iv = '', string $algo = 'AES-128-CBC')
    {
        $key = $key ?: config('aes.key');
        $iv = $iv ?: config('aes.iv');
        return openssl_decrypt(base64_decode($encryptString),$algo,$key,true,$iv);
    }

    /* 加密 AES加密串
    *
    * @param string $encryptString
    * @param string $key
    * @param string $iv
    * @param string $algo
    * @return false|string
    */
    public static function encryptAesString(string $encryptString , string $key = '', string $iv = '', string $algo = 'AES-128-CBC')
    {
        $key = $key ?: config('aes.key');
        $iv = $iv ?: config('aes.iv');
        return openssl_encrypt(base64_encode($encryptString), $algo, $key, 0, $iv);
    }

    /**
     * 获取当前格式化的时间
     *
     * @param string $format
     * @return string
     */
    public static function getDateTime(string $format = 'Y-m-d H:i:s')
    {
        return Carbon::now()->format($format);
    }

    /**
     * 格式化时间戳
     *
     * @param string $timeStamp
     * @param string $format
     * @return string
     */
    public static function formatTime(string $timeStamp, string $format = 'Y-m-d H:i:s')
    {
        return Carbon::createFromTimestamp($timeStamp)->format($format);
    }

    /**
     * 对密码 hash 操作
     *
     * @param string $password
     * @return string
     */
    public static function hashPwd(string $password)
    {
        return Hash::make($password);
    }

    /**
     * 校验 hash 密码
     *
     * @param string $password
     * @param string $pwdHashStr
     * @return bool
     */
    public static function hashverifyPwd(string $password, string $pwdHashStr)
    {
        return Hash::check($password, $pwdHashStr);
    }

    /**
     * 创建目录
     *
     * @param string $dirs
     * @return bool
     */
    public static function mkdirs(string $dirs)
    {
        if(!file_exists($dirs)) {
            mkdir($dirs, 0775, true);
            chmod($dirs, 754);
            return true;
        }
        return false;
    }

    /**
     * 校验手机号号码格式
     *
     * @param string $mobile
     * @return false|int
     */
    public static function verifyMobileFormat(string $mobile)
    {
        return preg_match("/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|4|3|5|6|7|8|9]|17[0-9]|16[0-9]|19[0-9])\d{8}$/", $mobile);
    }

    /**
     * 获取文件大小，字节
     *
     * @param string $filepath
     * @return false|int
     */
    public static function getFileSize(string $filepath)
    {
        if(!file_exists($filepath))return 0;
        return filesize($filepath);
    }

    /**
     * @param string $filepath
     * @param string $format
     * @return int|string
     */
    public static function getFileSizeName(string $filepath)
    {
        $filesize = self::getFileSize($filepath);
        if ($filesize >= 1073741824) {
            $filesize = round($filesize / 1073741824 * 100) / 100 . 'GB';
        } elseif ($filesize >= 1048576) {
            $filesize = round($filesize / 1048576 * 100) / 100 . 'MB';
        } elseif ($filesize >= 1024) {
            $filesize = round($filesize / 1024 * 100) / 100 . 'KB';
        } else {
            $filesize = $filesize . ' 字节';
        }
        return $filesize;
    }

    /**
     * 获取文件路径名称信息
     *
     * @param string $filepath
     * @param string $mode
     * @return array|string|string[]
     */
    public static function getFileInfo(string $filepath, string $mode = 'PATHINFO_EXTENSION')
    {
        return pathinfo($filepath, $mode);
    }

    /**
     * 格式化数据
     *
     * @param string $num
     * @param int $precision
     */
    public static function formatNum(string $num, int $precision =2)
    {
        return sprintf("%." . $precision . "f", $num);
    }

    /**
     * 前面补0生成指定长度的字符串
     * @param string $param
     * @param int $length
     */

    public static function addCode(string $param ,int $length = 10)
    {
        //要补0的位数
        $length1 = $length - strlen($param);
        $str ='';
        for ($i = 0; $i < $length1; $i++) {
            $str .=  '0';
        }

        $str = $str.$param;
        return $str;
    }

    /**
     * 校验指定参数是否包含字母数字 且长度是否符合
     * @param string $param
     * @param int $length
     * @return false|void
     */
    public static function checkInfoIncloudeNumer(string $param,int $length = 10)
    {

        if (mb_strlen($param) > $length)
             return false;

        if(!preg_match("/^[a-z\d]*$/i",$param))
            return false;

        return true;
    }

    /**
     * 权限菜单分类
     * @param $menu
     * @param $id
     * @param $pid
     * @param $name
     * @param $child
     * @param $level
     * @return array
     */
    public static function toReturnTwoTree($menu=[], $id='id', $pid='authPid', $name='authName', $child='nodes', $level=0)
    {
        $tree = [];
        $tmp_data = [];
        foreach($menu as $value){
            $tmp_data[$value[$id]] = $value;
        }
        foreach($tmp_data as $key=>$value){
            $tmp_data[$key]['text'] = $value[$name];    // 符合树状分类的结构
            if($value[$pid] == $level){   // 最顶级分类
                $tree[] = &$tmp_data[$key];
                continue;
            }
            //找到其父类
            $tmp_data[$value[$pid]][$child][] = &$tmp_data[$key];
        }
        return $tree;
    }

    /**
     * 字母+数字+位数校验
     * @param string $param
     * @return bool
     */
    public static function checkPass(string $param)
    {
        if ( mb_strlen($param)<8 || mb_strlen($param)>20)
            return false;

        if (!preg_match("/^(([a-z]+[0-9]+)|([0-9]+[a-z]+))[a-z0-9]*$/i",$param))
            return false;

        return true;
    }

    /**
     * 随机密码
     * @param int $length
     * @return string
     */
    public static function randomKeys(int $length) {

        $returnStr='';

        $pattern = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ';

        for($i = 0; $i < $length; $i ++) {

            $returnStr .= $pattern (mt_rand ( 0, 61 )); //生成php随机数

        }
        return $returnStr;
    }


    /**
     * 随机数字
     * @param int $length
     * @return string
     */
    public static function create_str(int $length) {
        $chars = "0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 随机号码
     * @param int $legth
     * @return string
     * @author shen.zk
     * @date 2023-08-28 20:04
     */
    public static function build_hash_no(int $legth = 0): string
    {
        $yCode = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
        return $orderSn = $yCode[intval(date('Y')) - 2018] . strtoupper(dechex(date('m'))) . date('d') . substr((string)time(), -5) . substr((string)microtime(), 2, 5) . sprintf('%02d', rand(0, 0)) . date('Ymd') . substr(implode(null, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8).rand(10000,99999);
    }

    /**
     * ugc订单号
     * @return string
     * Author:xsc
     * Time:2023/10/9 15:26
     */
    public function build_ugc_order_no()
    {
        return 'UGC' . date('YmdHis') . sprintf('%03d', intval(explode(' ', microtime())[0] * 1000)) . mt_rand(100000, 999999);
    }

}
